package com.changan.exception;

import com.changan.response.Result;
import com.changan.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

/**
 * @program: xinguan-parent
 * @description: 全局异常处理器,它只会处理Controller层的异常
 * @author: Mr.Nie
 * @create: 2022-05-21 11:00
 **/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler(value = ArithmeticException.class)
    public Result exception(ArithmeticException e){
        e.printStackTrace();
        log.error("出现了异常");
        return Result.error(ResultCode.ARITHMETIC_EXCEPTION);
    }

    @ResponseBody
    @ExceptionHandler(value = NullPointerException.class)
    public Result exception(NullPointerException e){
        e.printStackTrace();
        log.error("出现了异常");
        return Result.error(ResultCode.NULL_POINTER_EXCEPTION);
    }

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result exception(Exception e){
        e.printStackTrace();
        log.error("出现异常:"+ e.getMessage()+"----------------");
        return Result.error();
    }

    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public Result exception(BusinessException e){
        e.printStackTrace();
        log.error("出现了异常"+e.getErrMsg());
        return Result.error().code(e.getCode()).message(e.getErrMsg());
    }

    //处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Result BindExceptionHandler(BindException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return Result.error().message(message);
    }

    //处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
    /*@ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ResponseBean ConstraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return ResponseBean.error(message);
    }*/

    //处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return Result.error().message(message);
    }

    /**
     * 处理servlet异常
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = ServletException.class)
    @ResponseBody
    public  Result servletExceptionHandler(HttpServletRequest req, ServletException e){
        log.error("web服务器异常 {}",e.getMessage());
        return Result.error().message(e.getMessage());
    }

    /**
     * 处理自定义的业务异常
     * @param req
     * @param e
     * @return
     */
    /*@ExceptionHandler(value = BusinessException.class)
    @ResponseBody
    public  Result bizExceptionHandler(HttpServletRequest req, BusinessException e){
        log.error("业务异常=>{}",e.getErrMsg());
        return Result.error().code(e.getCode()).message(e.getErrMsg());
    }*/


    /**
     * shiro的异常
     * @param e
     * @return
     */
    /*@ExceptionHandler(ShiroException.class)
    public ResponseBean handle401(ShiroException e) {
        log.error("shiro异常=>{}",e.getMessage());
        return new ResponseBean(401, e.getMessage(), null);
    }*/


    /**
     * 获取状态码
     * @param request
     * @return
     */
    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }
}
